#ifndef GLWIDGET_H
#define GLWIDGET_H

//================================================================================================================================
//================================================================================================================================
#include <QtGui/QMouseEvent>
#include <QtOpenGL/QGLWidget>

//================================================================================================================================
//================================================================================================================================
// Виджет для отрисовки конечноэлементной сетки (с помощью OpenGL)
class GLWidget : public QGLWidget
{
    Q_OBJECT

public:
    GLWidget(QWidget *parent = 0) : QGLWidget(parent) {setCursor(Qt::OpenHandCursor);}

    //============================================================================================================================
    // Отобразить сетку. Данные о графическом представлении сетки считываются и записываются в буфер OpenGL, после чего посылается
    // запрос на перерисовку виджета. Метод триангуляции - фронтальный.
    //============================================================================================================================
    void paintMesh(QString filename);

    //============================================================================================================================
    // Отобразить сетку. Данные о графическом представлении сетки считываются и записываются в буфер OpenGL, после чего посылается
    // запрос на перерисовку виджета. Метод триангуляции - Делоне.
    //============================================================================================================================
    void paintMesh(int method);

public slots:
    //============================================================================================================================
    // Установить границы отображаемой сцены по умолчанию (в системе координат соответствующей отображаемой сетке).
    //============================================================================================================================
    void resetSceneLimits()
    {
        m_Scene.top = m_Scene.dtop;
        m_Scene.left = m_Scene.dleft;
        m_Scene.right = m_Scene.dright;
        m_Scene.bottom = m_Scene.dbottom;
        update();
    }

protected:
    //============================================================================================================================
    // При прокрутке колеса изображение приближается/отдаляется (увеличивается/уменьшается).
    //============================================================================================================================
    void wheelEvent(QWheelEvent *e)
    {
        e->delta() > 0 ? m_Scene.zoom(1.25) : m_Scene.zoom(0.75);
        update();
    }

    //============================================================================================================================
    // При зажатой ЛКМ движение мыши вызывает перемещение изображения. Полезно, если изображение не помещается в окне целиком.
    //============================================================================================================================
    void mouseMoveEvent(QMouseEvent *e)
    {
        if(e->buttons().testFlag(Qt::LeftButton))
        {
            double delta_x = (m_StartMousePos.x() - e->x())*(m_Scene.width())/width();
            double delta_y = (m_StartMousePos.y() - e->y())*(m_Scene.height())/height();
            m_Scene.shift(delta_x, -delta_y);
            m_StartMousePos = e->pos();
        }
        update();
    }

    //============================================================================================================================
    // Включение режима перемещения(перетаскивания) изображения с помощью мыши.
    //============================================================================================================================
    void mousePressEvent(QMouseEvent *e)
    {
        if(e->button() == Qt::LeftButton)
        {
            setCursor(Qt::ClosedHandCursor);
            m_StartMousePos = e->pos();
        }
    }

    //============================================================================================================================
    // Выключение режима перемещения(перетаскивания) изображения с помощью мыши.
    //============================================================================================================================
    void mouseReleaseEvent(QMouseEvent *e)
    {
        if(e->button() == Qt::LeftButton)
            setCursor(Qt::OpenHandCursor);
    }

    //============================================================================================================================
    // Настройка OpenGL (Установка флагов OpenGL и т.д.)
    //============================================================================================================================
    void initializeGL(){qglClearColor(Qt::white);}

    //============================================================================================================================
    // Адоптация вывода OpenGL к размеру виджета.
    //============================================================================================================================
    void resizeGL(int w, int h){glViewport(0,0,w,h);}

    //============================================================================================================================
    // Отрисовка OpenGL.
    //============================================================================================================================
    void paintGL();

private:
    struct
    {
        double left, right, top, bottom;      // Границы сцены.
        double dleft, dright, dtop, dbottom;  // Границы сцены по умолчнанию.

        // Ширина сццены.
        double width() {return right - left;}
        // Высота сцены.
        double height() {return top - bottom;}
        // Центральная точка сцены.
        QPointF centre(){return QPointF(left + width()/2., bottom + height()/2.);}
        // Сдвиг сцены.
        void shift(double v, double h){left += v; right += v; top +=h; bottom += h;}
        // Масштабирование сцены.
        void zoom(double s)
        {
            double w = width();
            double h = height();
            QPointF c = centre();
            left = c.x() - w*s/2.;
            right = c.x() + w*s/2.;
            top = c.y() + h*s/2.;
            bottom = c.y() - h*s/2.;}
    }m_Scene;               // Отображаемая сцена в системе координат, соответствующей сетке.

    GLuint m_AreaListID;    // Идентификатор списка отображения контуров области.
    GLuint m_NetListID;     // Идентификатор списка отображения конечноэлементной сетки.

    QPoint m_StartMousePos; // Начальная позиция мыши при движении с нажатой левой кнопкой. Событие mouseMoveEvent позволяет получить.
                            // лишь текущие координаты мыши. Нам же нужно знать и начальные координаты мыши для того, чтобы вычислить.
                            // пройденный мышью путь.
};

#endif // GLWIDGET_H
